home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / gfx / misc / gnuplot-src.lha / gnuplot-3.7.1src / gnuplot-3.7.1.lha / gnuplot-3.7.1 / binary.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-11-04  |  12.2 KB  |  420 lines

  1. #ifndef lint*), "conSid = "$Id: binary.c,v 1.4 1998/11/04 14:52:39 lhecking Exp $";
  2. #endif
  3.  
  4. /*
  5.  * The addition of gnubin and binary, along with a small patch
  6.  * to command.c, will permit gnuplot to plot binary files.
  7.  * gnubin  - contains the code that relies on gnuplot include files
  8.  *                     and other definitions
  9.  * binary      - contains those things that are independent of those 
  10.  *                     definitions and files
  11.  *
  12.  * With these routines, hidden line removal of your binary data is possible!
  13.  *
  14.  * Last update:  3/29/92 memory allocation bugs fixed. jvdwoude@hut.nl
  15.  *               3/09/92 spelling errors, general cleanup, use alloc with no
  16.  *                       nasty fatal errors
  17.  *               3/03/92 for Gnuplot 3.24.
  18.  * Created from code for written by RKC for gnuplot 2.0b.
  19.  *
  20.  * Copyright (c) 1991,1992 Robert K. Cunningham, MIT Lincoln Laboratory
  21.  *
  22.  */
  23.  
  24. #include "plot.h"        /* We have to get TRUE and FALSE */
  25. #include "stdfn.h"
  26. #include "binary.h"
  27.  
  28. /* 
  29.  * This routine scans the first block of the file to see if the file is a 
  30.  * binary file.  A file is considered binary if 10% of the characters in it 
  31.  * are not in the ascii character set. (values < 128), or if a NUL is found.
  32.  * I hope this doesn't break when used on the bizzare PC's.
  33.  */
  34. int is_binary_file(fp)
  35. register FILE *fp;
  36. {
  37.     register int i, len;
  38.     register int odd;        /* Contains a count of the odd characters */
  39.     long where;
  40.     register unsigned char *c;
  41.     unsigned char buffer[512];
  42.  
  43.     if ((where = ftell(fp)) == -1) {    /* Find out where we start */
  44.     fprintf(stderr, "Notice: Assuming unseekable data is not binary\n");
  45.     return (FALSE);
  46.     } else {
  47.     rewind(fp);
  48.  
  49.     len = fread(buffer, sizeof(char), 512, fp);
  50.     if (len <= 0)        /* Empty file is declared ascii */
  51.         return (FALSE);
  52.  
  53.     c = buffer;
  54.  
  55.     /* now scan buffer to look for odd characters */
  56.     odd = 0;
  57.     for (i = 0; i < len; i++, c++) {
  58.         if (!*c) {        /* NUL _never_ allowed in text */
  59.         odd += len;
  60.         break;
  61.         } else if ((*c & 128) ||    /* Meta-characters--we hope it's not formatting */
  62.                (*c == 127) ||    /* DEL */
  63.                (*c < 32 &&
  64.             *c != '\n' && *c != '\r' && *c != '\b' &&
  65.             *c != '\t' && *c != '\f' && *c != 27 /*ESC */ ))
  66.         odd++;
  67.     }
  68.  
  69.     fseek(fp, where, 0);    /* Go back to where we started */
  70.  
  71.     if (odd * 10 > len)    /* allow 10% of the characters to be odd */
  72.         return (TRUE);
  73.     else
  74.         return (FALSE);
  75.     }
  76. }
  77.  
  78.  
  79. /*========================= I/O Routines ================================
  80.   These may be useful for situations other than just gnuplot.  Note that I 
  81.   have included the reading _and_ the writing routines, so others can create 
  82.   the file as well as read the file.
  83. */
  84.  
  85. /*
  86.    This function reads a matrix from a stream
  87.  
  88.    This routine never returns anything other than vectors and arrays
  89.    that range from 0 to some number.  
  90.  
  91.  */
  92. #define START_ROWS 100        /* Each of these must be at least 1 */
  93. #define ADD_ROWS 50
  94. int fread_matrix(fin, ret_matrix, nr, nc, row_title, column_title)
  95. FILE *fin;
  96. float GPFAR *GPFAR * GPFAR * ret_matrix, GPFAR * GPFAR * row_title,
  97.  GPFAR * GPFAR * column_title;
  98. int *nr, *nc;
  99. {
  100.     float GPFAR *GPFAR * m, GPFAR * rt, GPFAR * ct;
  101.     register int num_rows = START_ROWS;
  102.     register int num_cols;
  103.     register int current_row = 0;
  104.     register float GPFAR *GPFAR * temp_array;
  105.     float fdummy;
  106.  
  107.     if (fread(&fdummy, sizeof(fdummy), 1, fin) != 1)
  108.     return FALSE;
  109.  
  110.     num_cols = (int) fdummy;
  111.  
  112.     /* 
  113.        Choose a reasonable number of rows,
  114.        allocate space for it and continue until this space
  115.        runs out, then extend the matrix as necessary.
  116.      */
  117.     ct = vector(0, num_cols - 1);
  118.     fread(ct, sizeof(*ct), num_cols, fin);
  119.  
  120.     rt = vector(0, num_rows - 1);
  121.     m = matrix(0, num_rows - 1, 0, num_cols - 1);
  122.  
  123.     while (fread(&rt[current_row], sizeof(rt[current_row]), 1, fin) == 1) {
  124.     /* We've got another row */
  125.     if (fread(m[current_row], sizeof(*(m[current_row])), num_cols, fin) != num_cols)
  126.         return (FALSE);    /* Not a True matrix */
  127.  
  128.     current_row++;
  129.     if (current_row >= num_rows) {    /* We've got to make a bigger rowsize */
  130.         temp_array = extend_matrix(m, 0, num_rows - 1, 0, num_cols - 1,
  131.                   num_rows + ADD_ROWS - 1, num_cols - 1);
  132.         rt = extend_vector(rt, 0, num_rows - 1, num_rows + ADD_ROWS - 1);
  133.  
  134.         num_rows += ADD_ROWS;
  135.         m = temp_array;
  136.     }
  137.     }
  138.     /*  finally we force the matrix to be the correct row size */
  139.     /*  bug fixed. procedure called with incorrect 6th argument.
  140.      *   jvdwoude@hut.nl */
  141.     temp_array = retract_matrix(m, 0, num_rows - 1, 0, num_cols - 1, current_row - 1, num_cols - 1);
  142.     /* Now save the things that change */
  143.     *ret_matrix = temp_array;
  144.     *row_title = retract_vector(rt, 0, num_rows - 1, current_row - 1);
  145.     *column_title = ct;
  146.     *nr = current_row;        /* Really the total number of rows */
  147.     *nc = num_cols;
  148.     return (TRUE);
  149. }
  150.  
  151. /* This writes a matrix to a stream 
  152.    Note that our ranges are inclusive ranges--and we can specify subsets.
  153.    This behaves similarly to the xrange and yrange operators in gnuplot
  154.    that we all are familiar with.
  155.  */
  156. int fwrite_matrix(fout, m, nrl, nrh, ncl, nch, row_title, column_title)
  157. register FILE *fout;
  158. register float GPFAR *GPFAR * m, GPFAR * row_title, GPFAR * column_title;
  159. register int nrl, nrh, ncl, nch;
  160. {
  161.     register int j;
  162.     float length;
  163.     register int col_length;
  164.     register int status;
  165.     float GPFAR *title = NULL;
  166.  
  167.     length = (float) (col_length = nch - ncl + 1);
  168.  
  169.     if ((status = fwrite((char *) &length, sizeof(float), 1, fout)) != 1) {
  170.     fprintf(stderr, "fwrite 1 returned %d\n", status);
  171.     return (FALSE);
  172.     }
  173.     if (!column_title) {
  174.     column_title = title = vector(ncl, nch);
  175.     for (j = ncl; j <= nch; j++)
  176.         title[j] = (float) j;
  177.     }
  178.     fwrite((char *) column_title, sizeof(float), col_length, fout);
  179.     if (title) {
  180.     free_vector(title, ncl, nch);
  181.     title = NULL;
  182.     }
  183.     if (!row_title) {
  184.     row_title = title = vector(nrl, nrh);
  185.     for (j = nrl; j <= nrh; j++)
  186.         title[j] = (float) j;
  187.     }
  188.     for (j = nrl; j <= nrh; j++) {
  189.     fwrite((char *) &row_title[j], sizeof(float), 1, fout);
  190.     fwrite((char *) (m[j] + ncl), sizeof(float), col_length, fout);
  191.     }
  192.     if (title)
  193.     free_vector(title, nrl, nrh);
  194.  
  195.     return (TRUE);
  196. }
  197.  
  198. /*===================== Support routines ==============================*/
  199.  
  200. /******************************** VECTOR *******************************
  201.  *       The following routines interact with vectors.
  202.  *
  203.  *   If there is an error we don't really return - int_error breaks us out.
  204.  *
  205.  *   This subroutine based on a subroutine listed in "Numerical Recipies in C",
  206.  *   by Press, Flannery, Teukoilsky and Vetterling (1988).
  207.  *
  208.  */
  209. float GPFAR *vector(nl, nh)
  210. register int nl, nh;
  211. {
  212.     register float GPFAR *vec;
  213.  
  214.     if (!(vec = (float GPFAR *) gp_alloc((unsigned long) (nh - nl + 1) * sizeof(float), NULL))) {
  215.     int_error("not enough memory to create vector", NO_CARET);
  216.     return NULL;        /* Not reached */
  217.     }
  218.     return (vec - nl);
  219. }
  220.  
  221.  
  222. /* 
  223.  *  Free a vector allocated above
  224.  *
  225.  *   This subroutine based on a subroutine listed in "Numerical Recipies in C",
  226.  *   by Press, Flannery, Teukoilsky and Vetterling (1988).
  227.  *
  228.  */
  229. void free_vector(vec, nl, nh)
  230. float GPFAR *vec;
  231. int nl, nh;
  232. {
  233.     free(vec + nl);
  234. }
  235.  
  236. /************ Routines to modify the length of a vector ****************/
  237. float GPFAR *
  238.  extend_vector(vec, old_nl, old_nh, new_nh)
  239. float GPFAR *vec;
  240. register int old_nl, old_nh, new_nh;
  241. {
  242.     register float GPFAR *new_v;
  243.     new_v = (float GPFAR *) gp_realloc((void *) (vec + old_nl),
  244.            (unsigned long) (new_nh - old_nl + 1) * sizeof(float),
  245.                        "extend vector");
  246.     return new_v - old_nl;
  247. }
  248.  
  249. float GPFAR *
  250.  retract_vector(v, old_nl, old_nh, new_nh)
  251. float GPFAR *v;
  252. register int old_nl, old_nh, new_nh;
  253. {
  254.     register float GPFAR *new_v;
  255.     new_v = (float GPFAR *) gp_realloc((void *) (v + old_nl),
  256.                        (unsigned long) (new_nh - old_nl + 1) * sizeof(float), "retract vector");
  257.     return new_v - old_nl;
  258. }
  259.  
  260.  
  261. /***************************** MATRIX ************************
  262.  *
  263.  *       The following routines work with matricies
  264.  *
  265.  *      I always get confused with this, so here I write it down:
  266.  *               for nrl<= nri <=nrh and
  267.  *               for ncl<= ncj <=nch
  268.  *  
  269.  *   This matrix is accessed as:
  270.  *   
  271.  *     matrix[nri][ncj];
  272.  *     where nri is the offset to the pointer to a vector where the
  273.  *     ncjth element lies.
  274.  * 
  275.  *   If there is an error we don't really return - int_error breaks us out.
  276.  *
  277.  *   This subroutine based on a subroutine listed in "Numerical Recipies in C",
  278.  *   by Press, Flannery, Teukoilsky and Vetterling (1988).
  279.  *
  280.  */
  281. float
  282. GPFAR *GPFAR * matrix(nrl, nrh, ncl, nch)
  283. register int nrl, nrh, ncl, nch;
  284. {
  285.     register int i;
  286.     register float GPFAR *GPFAR * m;
  287.  
  288.     m = (float GPFAR * GPFAR *) gp_alloc((unsigned long) (nrh - nrl + 1) * sizeof(float GPFAR *), "matrix");
  289.     m -= nrl;
  290.  
  291.     for (i = nrl; i <= nrh; i++) {
  292.     if (!(m[i] = (float GPFAR *) gp_alloc((unsigned long) (nch - ncl + 1) * sizeof(float), NULL))) {
  293.         free_matrix(m, nrl, i - 1, ncl, nch);
  294.         int_error("not enough memory to create matrix", NO_CARET);
  295.         return NULL;
  296.     }
  297.     m[i] -= ncl;
  298.     }
  299.     return m;
  300. }
  301. /* 
  302.  * Free a matrix allocated above
  303.  *
  304.  *
  305.  *   This subroutine based on a subroutine listed in "Numerical Recipies in C",
  306.  *   by Press, Flannery, Teukoilsky and Vetterling (1988).
  307.  *
  308.  */
  309. void free_matrix(m, nrl, nrh, ncl, nch)
  310. float GPFAR *GPFAR * m;
  311. unsigned nrl, nrh, ncl, nch;
  312. {
  313.     register unsigned int i;
  314.  
  315.     for (i = nrl; i <= nrh; i++)
  316.     free((char GPFAR *) (m[i] + ncl));
  317.     free((char GPFAR *) (m + nrl));
  318. }
  319.  
  320. /*
  321.    This routine takes a sub matrix and extends the number of rows and 
  322.    columns for a new matrix
  323.  */
  324. float GPFAR *GPFAR * extend_matrix(a, nrl, nrh, ncl, nch, srh, sch)
  325. register float GPFAR *GPFAR * a;
  326. register int nrl, nrh, ncl, nch;
  327. register int srh, sch;
  328. {
  329.     register int i;
  330.     register float GPFAR *GPFAR * m;
  331.  
  332.     m = (float GPFAR * GPFAR *) gp_realloc((void *) (a + nrl), (unsigned long) (srh - nrl + 1) * sizeof(float GPFAR *), "extend matrix");
  333.  
  334.     m -= nrl;
  335.  
  336.     if (sch != nch) {
  337.     for (i = nrl; i <= nrh; i++) {    /* Copy and extend rows */
  338.         if (!(m[i] = extend_vector(m[i], ncl, nch, sch))) {
  339.         free_matrix(m, nrl, nrh, ncl, sch);
  340.         int_error("not enough memory to extend matrix", NO_CARET);
  341.         return NULL;
  342.         }
  343.     }
  344.     }
  345.     for (i = nrh + 1; i <= srh; i++) {
  346.     if (!(m[i] = (float GPFAR *) gp_alloc((unsigned long) (nch - ncl + 1) * sizeof(float), NULL))) {
  347.         free_matrix(m, nrl, i - 1, nrl, sch);
  348.         int_error("not enough memory to extend matrix", NO_CARET);
  349.         return NULL;
  350.     }
  351.     m[i] -= ncl;
  352.     }
  353.     return m;
  354. }
  355. /*
  356.    this routine carves a large matrix down to size
  357.  */
  358. float GPFAR *GPFAR * retract_matrix(a, nrl, nrh, ncl, nch, srh, sch)
  359. register float GPFAR *GPFAR * a;
  360. register int nrl, nrh, ncl, nch;
  361. register int srh, sch;
  362. {
  363.     register int i;
  364.     register float GPFAR *GPFAR * m;
  365.  
  366.     for (i = srh + 1; i <= nrh; i++) {
  367.     free_vector(a[i], ncl, nch);
  368.     }
  369.  
  370.     m = (float GPFAR * GPFAR *) gp_realloc((void *) (a + nrl), (unsigned long) (srh - nrl + 1) * sizeof(float GPFAR *), "retract matrix");
  371.  
  372.     m -= nrl;
  373.  
  374.     if (sch != nch) {
  375.     for (i = nrl; i <= srh; i++)
  376.         if (!(m[i] = retract_vector(m[i], ncl, nch, sch))) { {    /* Shrink rows */
  377.             free_matrix(m, nrl, srh, ncl, sch);
  378.             int_error("not enough memory to retract matrix", NO_CARET);
  379.             return NULL;
  380.         }
  381.         }
  382.     }
  383.     return m;
  384. }
  385.  
  386. float
  387. GPFAR *GPFAR * convert_matrix(a, nrl, nrh, ncl, nch)
  388. float GPFAR *a;
  389. register int nrl, nrh, ncl, nch;
  390.  
  391. /* allocate a float matrix m[nrl...nrh][ncl...nch] that points to the
  392.    matrix declared in the standard C manner as a[nrow][ncol], where 
  393.    nrow=nrh-nrl+1, ncol=nch-ncl+1.  The routine should be called with
  394.    the address &a[0][0] as the first argument.  This routine does
  395.    not free the memory used by the original array a but merely assigns
  396.    pointers to the rows. */
  397.  
  398. {
  399.     register int i, j, ncol, nrow;
  400.     register float GPFAR *GPFAR * m;
  401.  
  402.     nrow = nrh - nrl + 1;
  403.     ncol = nch - ncl + 1;
  404.     m = (float GPFAR * GPFAR *) gp_alloc((unsigned long) (nrh - nrl + 1) * sizeof(float GPFAR *), "convert_matrix");
  405.     m -= nrl;
  406.  
  407.     m[nrl] = a - ncl;
  408.     for (i = 1, j = nrl + 1; i <= nrow - 1; i++, j++)
  409.     m[j] = m[j - 1] + ncol;
  410.     return m;
  411. }
  412.  
  413.  
  414. void free_convert_matrix(b, nrl, nrh, ncl, nch)
  415. float GPFAR *GPFAR * b;
  416. register int nrl, nrh, ncl, nch;
  417. {
  418.     free((char *) (b + nrl));
  419. }
  420.